#include <stdio.h>
#include "data.h"

char keyvals[] = {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 
		'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'};

char possibles[3][27]={0};

int main()
{	
	// This first section cuts down our list of possible key values to those which
	// produce printable ASCII characters. 
	for(int offset = 0; offset < 3; offset++)
	{
		for (unsigned char c = 0; c < sizeof keyvals; c++)
		{
			for(size_t checkc = offset; checkc < sizeof data; checkc+=3)
			{
				if ((keyvals[c] ^ data[checkc]) > 0x7E || (keyvals[c] ^ data[checkc]) < 0x20)
				{
				//	printf("Bad: %c %d %d\n", keyvals[c], data[checkc], data[checkc] ^ keyvals[c]);
					keyvals[c] = -keyvals[c];
					break;
				}
			}
		}
		
		int i = 0;
		printf("Possible key values slot %d: ", offset+1);
		for (unsigned char c = 0; c < sizeof keyvals; c++)
		{
			if (keyvals[c] > 0)
			{
				printf("%c ", keyvals[c]);
				possibles[offset][i++] = keyvals[c];
			}
			else
			{
				keyvals[c] = -keyvals[c];
			}
		}
			printf("\n");
		
	}
	
	// This commented out section prints all truly possible versions of the
	// first 30 characters in the encrypted message.
	// After our first heuristic, there are only 540 possibilities.
	// reduced from 26^3, or 17,576
	/*
	int inds[3];
	for(inds[2] = 0; possibles[2][inds[2]] != 0; inds[2]++)
		for(inds[0] = 0; possibles[0][inds[0]] != 0; inds[0]++)
			for(inds[1] = 0; possibles[1][inds[1]] != 0; inds[1]++)
			{
				for(int i = 0; i < 3; i++)
					printf("%c", possibles[i][inds[i]]);
				printf(": ");
				for(int d = 0; d < 30; d++)
					printf("%c", possibles[d%3][inds[d%3]] ^ data[d]);
				printf("\n");
			}
	*/
	
	// Upon manually scanning the list of possibilities, a passage from the
	// Gospel of John is visible. Revealing a related key...
	char key[]="god";
	unsigned int answer = 0;
	for (size_t c = 0; c < sizeof data; c++)
	{
		answer+= data[c] ^ key[c%3];
	}
	printf("Answer: %d\n", answer);
	return 0;
}
